/*
 *  modifier: Honrun
 *  date:     2022/08/17 21:42
 */
#include "stdio.h"
#include "stdint.h"
#include "DevicesMemPool.h"


/* 内存池空闲空闲链表 */
MemPoolType g_typeMemPoolList = {0};
/* 需要增加 MEM_HEAP_ROUNDUP_VALUE 个长度，以保证字节对齐 */
static uint8_t st_MemPoolHeap[(DEVICES_MEM_POOL_BLOCK_SIZE * DEVICES_MEM_POOL_BLOCK_COUNT) + MEM_POOL_ROUNDUP_VALUE] = {0};


static int8_t cMemPoolCreate(MemPoolType *ptypeMemPoolHead, uint8_t *pucMemPoolHeap, int32_t iBlockSize, int32_t iBlockCount);
static int8_t cMemPoolInsert(MemPoolType *ptypeMemPoolBase, MemPoolType *ptypeMemPoolNow);
static int8_t cMemPoolRemove(MemPoolType *ptypeMemPoolNow);


void vMemPoolInit(void)
{
    cMemPoolCreate(&g_typeMemPoolList, st_MemPoolHeap, DEVICES_MEM_POOL_BLOCK_SIZE, DEVICES_MEM_POOL_BLOCK_COUNT);
}

static int8_t cMemPoolCreate(MemPoolType *ptypeMemPoolHead, uint8_t *pucMemPoolHeap, int32_t iBlockSize, int32_t iBlockCount)
{
    MemPoolType *ptypeMemPoolNow = NULL;
    uint8_t *pucRoundUPAddr = NULL;

    if((ptypeMemPoolHead == NULL) || (pucMemPoolHeap == NULL) || (iBlockSize < sizeof(MemPoolType)) || (iBlockCount <= 0))
        return -1;

    /* 初始化头节点 */
    ptypeMemPoolHead->pNext = ptypeMemPoolHead->pPrevious = ptypeMemPoolHead;

    /* 地址 N 字节对齐 */
    pucRoundUPAddr = (uint8_t *)memPoolRoundUp((uint32_t)(pucMemPoolHeap), MEM_POOL_ROUNDUP_VALUE);

    while((iBlockCount--) > 0)
    {
        ptypeMemPoolNow = (MemPoolType *)(pucRoundUPAddr);
        pucRoundUPAddr += iBlockSize;

        /* 依次插入到空闲链表 */
        cMemPoolInsert(ptypeMemPoolHead, ptypeMemPoolNow);
    }

    return 0;
}


void *pvMemPoolMalloc(MemPoolType *ptypeMemPoolHead)
{
    void *pvHandle = NULL;

    if(ptypeMemPoolHead == NULL)
        return NULL;

    /* 没有剩余空闲空间 */
    if(ptypeMemPoolHead->pNext == ptypeMemPoolHead)
        return NULL;

    pvHandle = ptypeMemPoolHead->pNext;

    /* 取出空闲链表的第1个空间 */
    cMemPoolRemove(ptypeMemPoolHead->pNext);

    return pvHandle;
}

void vMemPoolFree(MemPoolType *ptypeMemPoolHead, void *pvMemAddr)
{
    MemPoolType *ptypeMemPoolNow = pvMemAddr;

    /* 插入到空闲链表 */
    cMemPoolInsert(ptypeMemPoolHead, ptypeMemPoolNow);
}


static int8_t cMemPoolInsert(MemPoolType *ptypeMemPoolBase, MemPoolType *ptypeMemPoolNow)
{
    if((ptypeMemPoolBase == NULL) || (ptypeMemPoolNow == NULL))
        return -1;

    ptypeMemPoolNow->pPrevious         = ptypeMemPoolBase->pPrevious;
    ptypeMemPoolBase->pPrevious->pNext = ptypeMemPoolNow;
    ptypeMemPoolBase->pPrevious        = ptypeMemPoolNow;
    ptypeMemPoolNow->pNext             = ptypeMemPoolBase;

    return 0;
}

static int8_t cMemPoolRemove(MemPoolType *ptypeMemPoolNow)
{
    if(ptypeMemPoolNow == NULL)
        return -1;

    ptypeMemPoolNow->pPrevious->pNext = ptypeMemPoolNow->pNext;
    ptypeMemPoolNow->pNext->pPrevious = ptypeMemPoolNow->pPrevious;

    return 0;
}
